package com.punai.apply.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.multi.ListValueMap;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.punai.apply.domain.ApplyCostMould;
import com.punai.apply.domain.ApplyCostMouldDetails;
import com.punai.apply.domain.contants.ApplyConstants;
import com.punai.apply.mapper.ApplyCostMouldDetailsMapper;
import com.punai.apply.mapper.ApplyCostMouldMapper;
import com.punai.apply.service.IApplyCostMouldService;
import com.punai.common.config.RuoYiConfig;
import com.punai.common.core.domain.CommonConstants;
import com.punai.common.core.domain.entity.SysDictData;
import com.punai.common.core.text.Convert;
import com.punai.common.exception.ServiceException;
import com.punai.common.utils.DictUtils;
import com.punai.common.utils.ParseContentUtil;
import com.punai.common.utils.SecurityUtils;
import com.punai.common.utils.StringUtils;
import com.punai.customer.domain.CusFeature;
import com.punai.customer.domain.CusMaterialCuItem;
import com.punai.customer.domain.CusMechanicalStaItem;
import com.punai.customer.mapper.CusExpenseCategoriesMapper;
import com.punai.customer.mapper.CusFeatureMapper;
import com.punai.customer.mapper.CusMaterialCuItemMapper;
import com.punai.customer.mapper.CusMechanicalStaItemMapper;
import com.punai.gk.domain.GkTemplate;
import com.punai.gk.domain.GkUseData;
import com.punai.gk.domain.bo.GkExcel;
import com.punai.gk.domain.constants.GkConstants;
import com.punai.gk.mapper.GkTemplateMapper;
import com.punai.gk.mapper.GkUseDataMapper;
import com.punai.standard.domain.StaVersion;
import com.punai.standard.domain.template.*;
import com.punai.standard.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 成本编制模板管理Service业务层处理
 *
 * @author zhx
 * @date 2023-03-21
 */
@Service
public class ApplyCostMouldServiceImpl extends ServiceImpl<ApplyCostMouldMapper,ApplyCostMould> implements IApplyCostMouldService
{
    @Autowired
    private ApplyCostMouldMapper applyCostMouldMapper;
    @Autowired
    private ApplyCostMouldDetailsMapper applyCostMouldDetailsMapper;
    @Autowired
    private StaVersionMapper staVersionMapper;

    @Autowired
    private CusFeatureMapper cusFeatureMapper;
    @Autowired
    private CusExpenseCategoriesMapper cusExpenseCategoriesMapper;
    @Autowired
    private GkUseDataMapper gkUseDataMapper;
    @Autowired
    private GkTemplateMapper gkTemplateMapper;
    @Autowired
    private StaGxChapterMapper staGxChapterMapper;
    @Autowired
    private StaGxFeeMapper staGxFeeMapper;
    @Autowired
    private StaFbChapterMapper staFbChapterMapper;
    @Autowired
    private StaFbFeeMapper staFbFeeMapper;
    @Autowired
    private StaClChapterMapper clChapterMapper;
    @Autowired
    private StaClFeeMapper clFeeMapper;
    @Autowired
    private StaJxChapterMapper jxChapterMapper;
    @Autowired
    private StaJxFeeMapper jxFeeMapper;
    @Autowired
    private StaLinkFbGxMapper staLinkFbGxMapper;
    @Autowired
    private StaLinkFeatureMapper staLinkFeatureMapper;
    @Autowired
    private StaLinkGxfeeCategoryMapper staLinkGxfeeCategoryMapper;
    @Autowired
    private StaGxFeatureConsumeMapper staGxFeatureConsumeMapper;
    @Autowired
    private StaSubpkLinkConsumeAddressMapper staSubpkLinkConsumeAddressMapper;
    @Autowired
    private StaSubpkLinkConsumeMapper staSubpkLinkConsumeMapper;
    @Autowired
    private StaGxLinkGkMapper staGxLinkGkMapper;
    @Autowired
    private StaGxLinkGkCategoriesMapper staGxLinkGkCategoriesMapper;
    @Autowired
    private StaLinkMaterialStaCusMapper staClLinkMapper;
    @Autowired
    private StaLinkMechanicalStaCusMapper staJxLinkMapper;
    @Autowired
    private CusMaterialCuItemMapper cusClMapper;
    @Autowired
    private CusMechanicalStaItemMapper cusJxMapper;



    /**
     * 查询成本编制模板管理
     *
     * @param id 成本编制模板管理主键
     * @return 成本编制模板管理
     */
    @Override
    public ApplyCostMould selectApplyCostMouldById(String id)
    {
        return applyCostMouldMapper.selectApplyCostMouldById(id);
    }

    /**
     * 查询成本编制模板管理列表
     *
     * @param applyCostMould 成本编制模板管理
     * @return 成本编制模板管理
     */
    @Override
    public List<ApplyCostMould> selectApplyCostMouldList(ApplyCostMould applyCostMould)
    {
        return applyCostMouldMapper.selectApplyCostMouldList(applyCostMould);
    }

    /**
     * 新增成本编制模板管理
     *
     * @param applyCostMould 成本编制模板管理
     * @return 结果
     */
    @Override
    @Transactional
    public int insertApplyCostMould(ApplyCostMould applyCostMould)
    {
        Long companyId = applyCostMould.getCompanyId();
        BigDecimal verNum = applyCostMouldMapper.selectMaxVerNum(companyId).add(new BigDecimal("0.1"));
        Integer maxOrderNum = applyCostMouldMapper.selectMaxOrderNum(companyId);

        applyCostMould.setName("模板"+verNum);
        applyCostMould.setVerNum(verNum);
        applyCostMould.setOrderNum(++maxOrderNum);
        applyCostMould.setState("0");
        applyCostMouldMapper.insert(applyCostMould);

        List<StaVersion> gxVersions = staVersionMapper.selectIdAndSpecByType(companyId, ApplyConstants.GX_TYPE);
        List<StaVersion> fbVersions = staVersionMapper.selectIdAndSpecByType(companyId, ApplyConstants.FB_TYPE);
        String clNewestId = staVersionMapper.getNewestId(companyId, ApplyConstants.CL_TYPE, null);
        String jxNewestId = staVersionMapper.getNewestId(companyId, ApplyConstants.JX_TYPE, null);

        if(CollUtil.isEmpty(gxVersions)){
            throw new ServiceException("标准费用项未发布新版本");
        }
        if(CollUtil.isEmpty(fbVersions)){
            throw new ServiceException("成本费用项未发布新版本");
        }
        if(StringUtils.isEmpty(clNewestId)){
            throw new ServiceException("材料费用项未发布新版本");
        }
        if(StringUtils.isEmpty(jxNewestId)){
            throw new ServiceException("机械费用项未发布新版本");
        }

        // 判断是否重复
        List<String> newestIds = new ArrayList<>();
        newestIds.addAll(gxVersions.stream().map(StaVersion::getId).collect(Collectors.toList()));
        newestIds.addAll(fbVersions.stream().map(StaVersion::getId).collect(Collectors.toList()));
        newestIds.add(clNewestId);
        newestIds.add(jxNewestId);

        String newestIdStr = StringUtils.join(newestIds, ",");

        Integer integer = applyCostMouldDetailsMapper.detectingDuplicates(companyId, newestIdStr);

        if(integer > 0){
            throw new ServiceException("已是最新版本");
        }

        String mouldId = applyCostMould.getId();

        List<SysDictData> fee_projecttype = DictUtils.getDictCache("fee_projecttype");
        Map<String, String> dictMap = fee_projecttype.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        Integer orderNum = 0;
        for (StaVersion gxVersion : gxVersions) {
            ApplyCostMouldDetails applyCostMouldDetails = new ApplyCostMouldDetails();
            applyCostMouldDetails.setCompanyId(companyId);
            applyCostMouldDetails.setMouldId(mouldId);
            applyCostMouldDetails.setName(dictMap.get(gxVersion.getSpecId())+ApplyConstants.GX_NAME);
            applyCostMouldDetails.setVersionId(gxVersion.getId());
            applyCostMouldDetails.setType(ApplyConstants.GX_TYPE);
            applyCostMouldDetails.setSpecId(gxVersion.getSpecId());
            applyCostMouldDetails.setOrderNum(++orderNum);
            applyCostMouldDetailsMapper.insert(applyCostMouldDetails);
        }

        for (StaVersion fbVersion : fbVersions) {
            ApplyCostMouldDetails applyCostMouldDetails = new ApplyCostMouldDetails();
            applyCostMouldDetails.setCompanyId(companyId);
            applyCostMouldDetails.setMouldId(mouldId);
            applyCostMouldDetails.setName(dictMap.get(fbVersion.getSpecId())+ApplyConstants.FB_NAME);
            applyCostMouldDetails.setVersionId(fbVersion.getId());
            applyCostMouldDetails.setType(ApplyConstants.FB_TYPE);
            applyCostMouldDetails.setSpecId(fbVersion.getSpecId());
            applyCostMouldDetails.setOrderNum(++orderNum);
            applyCostMouldDetailsMapper.insert(applyCostMouldDetails);
        }

        ApplyCostMouldDetails clApplyCostMouldDetails = new ApplyCostMouldDetails();
        clApplyCostMouldDetails.setCompanyId(companyId);
        clApplyCostMouldDetails.setMouldId(mouldId);
        clApplyCostMouldDetails.setName(ApplyConstants.CL_NAME);
        clApplyCostMouldDetails.setVersionId(clNewestId);
        clApplyCostMouldDetails.setType(ApplyConstants.CL_TYPE);
        clApplyCostMouldDetails.setOrderNum(++orderNum);
        applyCostMouldDetailsMapper.insert(clApplyCostMouldDetails);

        ApplyCostMouldDetails jxApplyCostMouldDetails = new ApplyCostMouldDetails();
        jxApplyCostMouldDetails.setCompanyId(companyId);
        jxApplyCostMouldDetails.setMouldId(mouldId);
        jxApplyCostMouldDetails.setName(ApplyConstants.JX_NAME);
        jxApplyCostMouldDetails.setVersionId(jxNewestId);
        jxApplyCostMouldDetails.setType(ApplyConstants.JX_TYPE);
        jxApplyCostMouldDetails.setOrderNum(++orderNum);
        applyCostMouldDetailsMapper.insert(jxApplyCostMouldDetails);

        return 200;
    }

    /**
     * 修改成本编制模板管理
     *
     * @param applyCostMould 成本编制模板管理
     * @return 结果
     */
    @Override
    public int updateApplyCostMould(ApplyCostMould applyCostMould)
    {
        return applyCostMouldMapper.updateById(applyCostMould);
    }

    @Override
    public String export(String id) {
        Long companyId = SecurityUtils.getCompanyId();
        List<ApplyCostMouldDetails> applyCostMouldDetails = applyCostMouldDetailsMapper.selectListByMouldId(id);

        List<SysDictData> fee_projecttype = DictUtils.getDictCache("fee_projecttype");
        Map<String, String> dictMap = null;
        if (fee_projecttype != null) {
            dictMap = fee_projecttype.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        } else {
            throw new RuntimeException("专业字典获取失败，请联系管理员");
        }
        List<SysDictData> fee_address = DictUtils.getDictCache("fee_address");
        Map<String, String> dictAddressMap;
        if (fee_address != null) {
            dictAddressMap = fee_address.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        } else {
            dictAddressMap = null;
            throw new RuntimeException("专业字典获取失败，请联系管理员");
        }

        String downloadPath = RuoYiConfig.getDownloadPath();
        String uuid = IdUtil.fastUUID();
        downloadPath = downloadPath + "excel-" + uuid + "/";

        File file = new File(downloadPath);
        if (!file.exists() && !file.isDirectory()) {
            file.mkdir();
        }

        String zdFile = downloadPath + "字典.xlsx";
        ExcelWriter zdExcelWriter = EasyExcel.write(zdFile).build();

        WriteSheet zdSheet1 = EasyExcel.writerSheet(0, "材机类别").head(CusExpenseCategoriesExcel.class).build();
        WriteSheet zdSheet2 = EasyExcel.writerSheet(1, "特征字典").head(CusFeature.class).build();
        Map<String, String> lbDictMap = new HashMap<>();
        Map<String, String> featureDictMap = new HashMap<>();
        Map<String, String> featureItemMap = new HashMap<>();
        Map<String, String> gkDictMap = new HashMap<>();

        List<CusFeature> cusFeatures = cusFeatureMapper.selectListExp(companyId);
        zdExcelWriter.write(cusFeatures, zdSheet2);
        featureDictMap = cusFeatures.stream().collect(Collectors.toMap(CusFeature::getId, CusFeature::getFeatureName));
        featureItemMap = cusFeatures.stream().collect(Collectors.toMap(CusFeature::getId, CusFeature::getFeatureValues));
        cusFeatures.clear();

        List<GkTemplate> gkTemplates = gkTemplateMapper.selectGkTemplateList(null);
        // 处理归口数据
        List<GkUseData> gkUseDataList = gkUseDataMapper.selectListExp(companyId);
        // 根据id分组
        Map<String, List<GkUseData>> groupByTemplate = gkUseDataList.stream().collect(Collectors.groupingBy(GkUseData::getTemplateId));
        int sheetNo = 2;
        for (GkTemplate gkTemplate : gkTemplates) {
            String templateId = gkTemplate.getId();
            String name = gkTemplate.getName();

            WriteSheet zdSheetGk = EasyExcel.writerSheet(sheetNo++, name + "归口").head(GkExcel.class).build();

            List<GkUseData> gkUseData = groupByTemplate.get(templateId);
            LinkedHashMap<String, List<GkUseData>> collect = new LinkedHashMap<>();
            for (GkUseData gkUseDatum : gkUseData) {
                String linkId = gkUseDatum.getLinkId();
                if(collect.containsKey(linkId)){
                    collect.get(linkId).add(gkUseDatum);
                }else {
                    List<GkUseData> gkUseDataListNew = new ArrayList<GkUseData>(1);
                    gkUseDataListNew.add(gkUseDatum);
                    collect.put(linkId,gkUseDataListNew);
                }
            }
            List<GkExcel> GkExcelList = new ArrayList<>();
            // 过滤
            Set<Map.Entry<String, List<GkUseData>>> entries = collect.entrySet();
            for (Map.Entry<String, List<GkUseData>> entry : entries) {
                List<GkUseData> value = entry.getValue();

                GkExcel gkExcel = new GkExcel();
                gkExcel.setId(entry.getKey());
                // 把每一个值都遍历,拿到所有属性
                for (GkUseData gkUseDatum : value) {
                    String codeDesc = gkUseDatum.getCodeDesc();
                    if(StringUtils.equals(codeDesc,GkConstants.GK_DEF_COLUMN.PID.getCodeDesc())){
                        gkExcel.setPid(gkUseDatum.getValueStr());
                    }else if(StringUtils.equals(codeDesc,GkConstants.GK_DEF_COLUMN.NAME.getCodeDesc())){
                        gkExcel.setName(gkUseDatum.getValueStr());
                    }else if(StringUtils.equals(codeDesc,GkConstants.GK_DEF_COLUMN.CONTENT.getCodeDesc())){
                        gkExcel.setContent(gkUseDatum.getValueStr());
                    }
                }
                GkExcelList.add(gkExcel);
            }
            // 排序组合
            ListValueMap<String,GkExcel> listValueMap = new ListValueMap<>();
            for (GkExcel gkExcel : GkExcelList) {
                String pid = Convert.toStr(gkExcel.getPid());
                listValueMap.putValue(pid,gkExcel);
            }
// 多个?
            List<GkExcel> rootList = listValueMap.get(CommonConstants.DEF_PID);

            // 每个是一组
            if(CollUtil.isNotEmpty(rootList)){
                Integer index = 0;
                // 装进map中
                for (GkExcel gkExcel : rootList) {
                    index++;
                    gkExcel.setIndexOne(index.toString());
                    getGkChildren(listValueMap,gkExcel,index.toString());
                }
            }
            List<GkExcel> flatList = new ArrayList<>();
            flattenTree(rootList,flatList);

            Map<String, String> gkDictMapNew = flatList.stream().collect(Collectors.toMap(GkExcel::getId, GkExcel::getName));
            gkDictMap.putAll(gkDictMapNew);
            gkDictMapNew.clear();

            zdExcelWriter.write(flatList, zdSheetGk);
            rootList.clear();
        }

        // 因为类别关联归口,所以先处理归口再处理类别
        List<CusExpenseCategoriesExcel> cusExpenseCategoriesExcelList = cusExpenseCategoriesMapper.selectListExp(companyId);
        setExpenseCategories(cusExpenseCategoriesExcelList,gkDictMap,lbDictMap);
        zdExcelWriter.write(cusExpenseCategoriesExcelList, zdSheet1);
        cusExpenseCategoriesExcelList.clear();
        zdExcelWriter.finish();

        // 标准费用项集合
        Map<String, StaGxFeeExcel> gxFeeMap = new HashMap<>();
        List<String> gxIds = new ArrayList<>();
        Map<String, List<String>> gxLinkFeatureIdMap = new HashMap<>();
        Map<String, List<String>> gxLinkCategoryIdMap = new HashMap<>();

        for (ApplyCostMouldDetails applyCostMouldDetail : applyCostMouldDetails) {
            String type = applyCostMouldDetail.getType();
            String versionId = applyCostMouldDetail.getVersionId();
            String specId = applyCostMouldDetail.getSpecId();
            String specName = dictMap.get(specId);
            if(StringUtils.equals(type,ApplyConstants.GX_TYPE)){
                String gxFile = downloadPath +  specName + "-" + ApplyConstants.GX_NAME + ".xlsx";
                ExcelWriter gxExcelWriter = EasyExcel.write(gxFile).build();
                // 章节id name集合
                Map<String, String> gxChapterMap;
                // 归口特征描述id name集合
                Map<String, String> featureDescribeGkMap = new HashMap<>();
                // 耗量特征描述id name集合
                Map<String, String> featureDescribeConsumeMap = new HashMap<>();

                Integer gxSheetNo = 0;
                List<StaTextExcel> textExcelList = new ArrayList<>();
                textExcelList.add(new StaTextExcel("① 章节", "费用项章节目录"));
                textExcelList.add(new StaTextExcel("② 标准费用项", "费用项基本信息（编码、名称、单位、计算规则、工作内容、适用范围、优先级、排序）"));
                textExcelList.add(new StaTextExcel("③ 关联特征", "费用项关联特征（特征项、特征值、适配开关状态、关联特征值）"));
                textExcelList.add(new StaTextExcel("④ 关联材机类别-费用项及类别", "费用项关联材机类别及费用项下直接挂架的材机的归口数据。"));
                textExcelList.add(new StaTextExcel("⑤ 关联归口-费用项及特征", "费用项关联归口数据：费用项分包模式，及归口数据；费用项指定特征后的分包模式及归口数据；"));
                textExcelList.add(new StaTextExcel("⑥ 关联归口-指定特征材机类别", "费用项关联归口数据：费用项指定特征后挂接的材机类别的归口数据。"));
                textExcelList.add(new StaTextExcel("⑦ 关联耗量地区", "当前专业费用项关联的耗量地区。"));
                textExcelList.add(new StaTextExcel("⑧ 耗量特征描述", "当前专业费用项设置耗量时，设置的费用项特征描述。"));
                textExcelList.add(new StaTextExcel("⑨ 关联地区耗量值", "当前专业费用项下地区对应的耗量值。"));

                WriteSheet gxSheet0 = EasyExcel.writerSheet(gxSheetNo++, "导出文件格式说明文档").head(StaTextExcel.class).build();
                gxExcelWriter.write(textExcelList, gxSheet0);

                WriteSheet gxSheet1 = EasyExcel.writerSheet(gxSheetNo++, "章节").head(StaGxChapterExcel.class).build();
                List<StaGxChapterExcel> staGxChapterExcelList = staGxChapterMapper.selectExportExcel(versionId);
                gxChapterMap = staGxChapterExcelList.stream().collect(Collectors.toMap(StaGxChapterExcel::getId, StaGxChapterExcel::getName));
                gxExcelWriter.write(staGxChapterExcelList,gxSheet1);
                staGxChapterExcelList.clear();

                WriteSheet gxSheet2 = EasyExcel.writerSheet(gxSheetNo++, "费用项").head(StaGxFeeExcel.class).build();
                List<StaGxFeeExcel> staGxFeeExcelList = staGxFeeMapper.selectExport(versionId);
                for (StaGxFeeExcel excel : staGxFeeExcelList) {
                    excel.setChapterName(gxChapterMap.get(excel.getChapterId()));
                    gxFeeMap.put(excel.getId(),excel);
                    excel.setContentStr(ParseContentUtil.parseContent(excel.getContent()));
                }
                gxIds = new ArrayList<>(gxFeeMap.keySet());
                gxExcelWriter.write(staGxFeeExcelList,gxSheet2);
                gxChapterMap.clear();
                staGxFeeExcelList.clear();

                WriteSheet gxSheet3 = EasyExcel.writerSheet(gxSheetNo++, "关联特征").head(StaGxLinkFeatureExcel.class).build();
                List<StaGxLinkFeatureExcel> staLinkFeatureExcelList = staLinkFeatureMapper.selectGxExport(versionId,gxIds);
                if(CollUtil.isNotEmpty(staLinkFeatureExcelList)){
                    gxLinkFeatureIdMap.putAll(staLinkFeatureExcelList.stream().collect(Collectors.groupingBy(StaGxLinkFeatureExcel::getItemId,
                            Collectors.mapping(StaGxLinkFeatureExcel::getFeatureId, Collectors.toList()))));
                }
                for (StaGxLinkFeatureExcel excel : staLinkFeatureExcelList) {
                    excel.setCode(gxFeeMap.get(excel.getItemId()).getCode());
                    excel.setItemName(gxFeeMap.get(excel.getItemId()).getName());
                    excel.setFeatureName(featureDictMap.get(excel.getFeatureId()));
                    excel.setItemFeature(featureItemMap.get(excel.getFeatureId()));
                }
                gxExcelWriter.write(staLinkFeatureExcelList,gxSheet3);
                staLinkFeatureExcelList.clear();

                WriteSheet gxSheet5 = EasyExcel.writerSheet(gxSheetNo++, "关联归口").head(StaGxLinkGkExcel.class).build();
                List<StaGxLinkGkExcel> staGxLinkGkExcelList = staGxLinkGkMapper.selectExport(versionId,gxIds);
                setGxLinkGkExcel(staGxLinkGkExcelList,gxFeeMap,featureDictMap,featureDescribeGkMap,gkDictMap);
                // 使用Stream API和Collectors.groupingBy()方法按gxId进行分组，并计算每个gxId的出现频率
                List<String> highFrequencyGxIds = new ArrayList<>();
                if(CollUtil.isNotEmpty(staGxLinkGkExcelList)) {
                    Map<String, Long> frequencyMap = staGxLinkGkExcelList.stream()
                            .collect(Collectors.groupingBy(StaGxLinkGkExcel::getGxId, Collectors.counting()));
                    // 获取出现频率高于两次的gxId
                    highFrequencyGxIds = frequencyMap.entrySet().stream()
                            .filter(entry -> entry.getValue() > 1)
                            .map(Map.Entry::getKey)
                            .collect(Collectors.toList());
                }
                gxExcelWriter.write(staGxLinkGkExcelList,gxSheet5);
                staGxLinkGkExcelList.clear();

                WriteSheet gxSheet4 = EasyExcel.writerSheet(gxSheetNo++, "关联类别").head(StaLinkGxfeeCategoryExcel.class).build();
                List<StaLinkGxfeeCategoryExcel> staLinkGxfeeCategoryExcelList = staLinkGxfeeCategoryMapper.selectExport(versionId,gxIds);

                if(CollUtil.isNotEmpty(staLinkGxfeeCategoryExcelList)) {
                    gxLinkCategoryIdMap.putAll(staLinkGxfeeCategoryExcelList.stream().collect(Collectors.groupingBy(StaLinkGxfeeCategoryExcel::getGxId,
                            Collectors.mapping(StaLinkGxfeeCategoryExcel::getCategoryId, Collectors.toList()))));
                }
                List<String> finalHighFrequencyGxIds = highFrequencyGxIds;
                List<String> oneLinkThreeGxIds = gxIds.stream().filter(item -> !finalHighFrequencyGxIds.contains(item)).collect(Collectors.toList());
                List<StaGxLinkGkCategoriesExcel> staGxLinkGkCategoriesExcelList = new ArrayList<>();
                if(CollUtil.isNotEmpty(oneLinkThreeGxIds)){
                    staGxLinkGkCategoriesExcelList.addAll(staLinkGxfeeCategoryMapper.selectByGxIds(versionId,oneLinkThreeGxIds));
                }

                for (StaLinkGxfeeCategoryExcel excel : staLinkGxfeeCategoryExcelList) {
                    excel.setCode(gxFeeMap.get(excel.getGxId()).getCode());
                    excel.setGxName(gxFeeMap.get(excel.getGxId()).getName());
                    excel.setCategoryName(lbDictMap.get(excel.getCategoryId()));
                }
                gxExcelWriter.write(staLinkGxfeeCategoryExcelList,gxSheet4);
                staLinkGxfeeCategoryExcelList.clear();

                WriteSheet gxSheet6 = EasyExcel.writerSheet(gxSheetNo++, "关联归口类别").head(StaGxLinkGkCategoriesExcel.class).build();
                staGxLinkGkCategoriesExcelList.addAll(staGxLinkGkCategoriesMapper.selectExport(versionId,gxIds));
                for (StaGxLinkGkCategoriesExcel excel : staGxLinkGkCategoriesExcelList) {
                    excel.setCode(gxFeeMap.get(excel.getGxId()).getCode());
                    excel.setGxName(gxFeeMap.get(excel.getGxId()).getName());
                    excel.setFeatureDescribe(featureDescribeGkMap.get(excel.getGxLinkGkId()));
                    excel.setCategoriesName(lbDictMap.get(excel.getCategoriesId()));

                    String gkItem = excel.getGkItem();
                    Map<String,String> gkItemMap = JSON.parseObject(gkItem, Map.class);
                    excel.setCB(gkDictMap.get(gkItemMap.get("CB")));
                    excel.setCS(gkDictMap.get(gkItemMap.get("CS")));
                }
                gxExcelWriter.write(staGxLinkGkCategoriesExcelList,gxSheet6);
                staGxLinkGkCategoriesExcelList.clear();

                WriteSheet gxSheet7 = EasyExcel.writerSheet(gxSheetNo++, "关联地区").head(StaAddressExcel.class).build();
                List<StaAddressExcel> staAddressExcelList = staSubpkLinkConsumeAddressMapper.selectExport(versionId);
                staAddressExcelList.forEach(excel -> excel.setName(dictAddressMap.get(excel.getId())));
                gxExcelWriter.write(staAddressExcelList,gxSheet7);
                staAddressExcelList.clear();
                WriteSheet gxSheet8 = EasyExcel.writerSheet(gxSheetNo++, "耗量特征描述").head(StaGxFeatureConsumeExcel.class).build();
                List<StaGxFeatureConsumeExcel> staGxFeatureConsumeExcelList = staGxFeatureConsumeMapper.selectExport(versionId,gxIds);
                setGxFeatureConsumeExcel(staGxFeatureConsumeExcelList, gxFeeMap, featureDictMap, featureDescribeConsumeMap, dictAddressMap);
                gxExcelWriter.write(staGxFeatureConsumeExcelList,gxSheet8);
                staGxFeatureConsumeExcelList.clear();

                WriteSheet gxSheet9 = EasyExcel.writerSheet(gxSheetNo, "关联耗量").head(StaSubpkLinkConsumeExcel.class).build();
                List<StaSubpkLinkConsumeExcel> staSubpkLinkConsumeExcelList = staSubpkLinkConsumeMapper.selectExport(versionId,gxIds);
                for (StaSubpkLinkConsumeExcel excel : staSubpkLinkConsumeExcelList) {
                    excel.setAddressName(dictAddressMap.get(excel.getAddress()));
                    excel.setCode(gxFeeMap.get(excel.getSubpkItemId()).getCode());
                    excel.setSubpkItemName(gxFeeMap.get(excel.getSubpkItemId()).getName());
                    excel.setFeatureDescribe(featureDescribeConsumeMap.get(excel.getLinkGxFeatureId()));
                    excel.setCategoriesName(lbDictMap.get(excel.getCategoriesId()));
                }
                gxExcelWriter.write(staSubpkLinkConsumeExcelList,gxSheet9);
                staSubpkLinkConsumeExcelList.clear();
                gxExcelWriter.finish();
            }else if(StringUtils.equals(type,ApplyConstants.FB_TYPE)){
                // 章节id name集合
                Map<String, String> fbChapterMap;
                // 成本费用项id name集合
                Map<String, String> fbFeeNameMap = new HashMap<>();
                // 成本费用项id code集合
                Map<String, String> fbFeeCodeMap = new HashMap<>();

                String fbFile = downloadPath + ApplyConstants.FB_NAME + "-" + specName + ".xlsx";
                ExcelWriter fbExcelWriter = EasyExcel.write(fbFile).build();

                WriteSheet fbSheet1 = EasyExcel.writerSheet(0, "章节").head(StaFbChapterExcel.class).build();
                WriteSheet fbSheet2 = EasyExcel.writerSheet(1, "费用项").head(StaFbFeeExcel.class).build();
                WriteSheet fbSheet3 = EasyExcel.writerSheet(2, "关联标准费用项").head(StaLinkFbGxExcel.class).build();
                WriteSheet fbSheet4 = EasyExcel.writerSheet(3, "关联特征").head(StaClJxLinkFeatureExcel.class).build();
                WriteSheet fbSheet5 = EasyExcel.writerSheet(4, "关联类别").head(StaLinkGxfeeCategoryExcel.class).build();

                List<StaFbChapterExcel> staFbChapterExcelList = staFbChapterMapper.selectExport(versionId);
                fbChapterMap = staFbChapterExcelList.stream().collect(Collectors.toMap(StaFbChapterExcel::getId, StaFbChapterExcel::getName));
                fbExcelWriter.write(staFbChapterExcelList,fbSheet1);
                staFbChapterExcelList.clear();

                // 成本费用项是组合而成的
                List<StaFbFeeExcel> staFbFeeExcelList = staFbFeeMapper.selectExport(versionId);

                List<StaLinkFbGxExcel> staLinkFbGxExcelList = staLinkFbGxMapper.selectExport(versionId);
                /**
                 * 1,组织成本费用项关联的标准费用项  -- fbGxIdMap
                 * 2,把标准费用项与特征id关联分组  -- gxLinkFeatureIdMap
                 * 3,Set集合(去重)存储关联的特征id
                 * 4,把成本费用项与关联特征写进表中
                 */
                List<StaClJxLinkFeatureExcel> fbLinkFeatureList = new ArrayList<>();
                List<StaLinkGxfeeCategoryExcel> fbLinkCategoryList = new ArrayList<>();
                if (CollUtil.isNotEmpty(staLinkFbGxExcelList)) {
                    Map<String, List<String>> fbGxIdMap = staLinkFbGxExcelList.stream().collect(Collectors.groupingBy(StaLinkFbGxExcel::getFbId,
                            Collectors.mapping(StaLinkFbGxExcel::getGxId, Collectors.toList())));

                    for (StaFbFeeExcel excel : staFbFeeExcelList) {
                        excel.setChapterName(fbChapterMap.get(excel.getChapterId()));
                        fbFeeNameMap.put(excel.getId(), excel.getName());
                        fbFeeCodeMap.put(excel.getId(), excel.getCode());

                        List<String> linkGxIds = fbGxIdMap.get(excel.getId());
                        Map<String, List<String>> fbContent = ParseContentUtil.getContentObj();

                        List<String> subRange = new ArrayList<>();
                        List<String> linkFeatureIds = new ArrayList<>();
                        List<String> linkCategoryIds = new ArrayList<>();
                        for (String gxId : linkGxIds) {
                            StaGxFeeExcel gxFeeExcel = gxFeeMap.get(gxId);
                            subRange.add(gxFeeExcel.getSuitableRange());
                            ParseContentUtil.mergeContent(fbContent, gxFeeExcel.getContent());

                            // 关联特征
                            List<String> gxLinkFeatureIds = gxLinkFeatureIdMap.get(gxId);
                            if(StringUtils.isNotEmpty(gxLinkFeatureIds)) {
                                linkFeatureIds.addAll(gxLinkFeatureIdMap.get(gxId).stream().filter(id1 -> !linkFeatureIds.contains(id1)).collect(Collectors.toList()));
                            }
                            // 关联特征
                            List<String> gxLinkCategoryIds = gxLinkCategoryIdMap.get(gxId);
                            if(StringUtils.isNotEmpty(gxLinkCategoryIds)){
                                linkCategoryIds.addAll(gxLinkCategoryIds.stream().filter(id1 -> !linkCategoryIds.contains(id1)).collect(Collectors.toList()));
                            }
                        }
                        for (String linkFeatureId : linkFeatureIds) {
                            fbLinkFeatureList.add(new StaClJxLinkFeatureExcel(null, null, excel.getCode(), excel.getName(), linkFeatureId, featureDictMap.get(linkFeatureId), featureItemMap.get(linkFeatureId)));
                        }
                        for (String linkCategoryId : linkCategoryIds) {
                            fbLinkCategoryList.add(new StaLinkGxfeeCategoryExcel(null, null, excel.getCode(), excel.getName(), linkCategoryId, lbDictMap.get(linkCategoryId), null));
                        }
                        //补充工作内容
                        ParseContentUtil.mergeContent(fbContent, excel.getContent());
                        excel.setContent(ParseContentUtil.parseContent(fbContent));
                        excel.setSuitableRange(StrUtil.join("；", subRange) + "；");
                    }
                }
                fbExcelWriter.write(staFbFeeExcelList, fbSheet2);
                staFbFeeExcelList.clear();
                for (StaLinkFbGxExcel excel : staLinkFbGxExcelList) {
                    excel.setFbCode(fbFeeCodeMap.get(excel.getFbId()));
                    excel.setFbName(fbFeeNameMap.get(excel.getFbId()));
                    excel.setGxCode(gxFeeMap.get(excel.getGxId()).getCode());
                    excel.setGxName(gxFeeMap.get(excel.getGxId()).getName());
                    if (excel.getSort() == 1) {
                        excel.setSubject("是");
                    }
                }
                fbExcelWriter.write(staLinkFbGxExcelList, fbSheet3);
                staLinkFbGxExcelList.clear();

                fbExcelWriter.write(fbLinkFeatureList, fbSheet4);
                fbLinkFeatureList.clear();

                fbExcelWriter.write(fbLinkCategoryList, fbSheet5);
                fbLinkCategoryList.clear();
                fbFeeCodeMap.clear();
                fbFeeNameMap.clear();
                fbExcelWriter.finish();

            }else if(StringUtils.equals(type,ApplyConstants.CL_TYPE)){
                String clFile = downloadPath +"材料.xlsx";
                ExcelWriter clExcelWriter = EasyExcel.write(clFile).build();
                Map<String, String> clChapterMap;
                List<String> clIds;
                Map<String, String> clNameMap = new HashMap<>();
                Map<String, String> clCodeMap = new HashMap<>();

                WriteSheet clSheet1 = EasyExcel.writerSheet(0, "章节").head(StaClChapterExcel.class).build();
                WriteSheet clSheet2 = EasyExcel.writerSheet(1, "费用项").head(StaClFeeExcel.class).build();
                WriteSheet clSheet3 = EasyExcel.writerSheet(2, "关联特征").head(StaClJxLinkFeatureExcel.class).build();
                WriteSheet clSheet4 = EasyExcel.writerSheet(3, "关联标准材料").head(StaClLinkExcel.class).build();

                List<StaClChapterExcel> staClChapterExcelList = clChapterMapper.selectExport(versionId);
                clChapterMap = staClChapterExcelList.stream().collect(Collectors.toMap(StaClChapterExcel::getId, StaClChapterExcel::getName));
                clExcelWriter.write(staClChapterExcelList,clSheet1);
                staClChapterExcelList.clear();
                List<StaClFeeExcel> staClFeeExcelList = clFeeMapper.selectExport(versionId);

                for (StaClFeeExcel excel : staClFeeExcelList) {
                    excel.setChapterName(clChapterMap.get(excel.getChapterId()));
                    clNameMap.put(excel.getId(),excel.getItemName());
                    clCodeMap.put(excel.getId(),excel.getCode());
                }
                clIds = new ArrayList<>(clNameMap.keySet());
                clExcelWriter.write(staClFeeExcelList,clSheet2);
                staClFeeExcelList.clear();
                clChapterMap.clear();
                List<StaClJxLinkFeatureExcel> staClLinkFeatureExcelList = staLinkFeatureMapper.selectClJxExport(versionId,clIds);
                for (StaClJxLinkFeatureExcel excel : staClLinkFeatureExcelList) {
                    excel.setItemName(clNameMap.get(excel.getItemId()));
                    excel.setCode(clCodeMap.get(excel.getItemId()));
                    excel.setFeatureName(featureDictMap.get(excel.getFeatureId()));
                }
                clExcelWriter.write(staClLinkFeatureExcelList,clSheet3);
                staClLinkFeatureExcelList.clear();

                List<StaClLinkExcel> staClLinkExcelList = staClLinkMapper.selectExport(versionId,clIds);
                List<CusMaterialCuItem> simplifyVoList = cusClMapper.selectSimplifyList(companyId);
                Map<String, String> cusClCodeMap = simplifyVoList.stream().collect(Collectors.toMap(CusMaterialCuItem::getId, CusMaterialCuItem::getCode));
                Map<String, String> cusClNameMap = simplifyVoList.stream().collect(Collectors.toMap(CusMaterialCuItem::getId, CusMaterialCuItem::getItemName));
                for (StaClLinkExcel excel : staClLinkExcelList) {
                    excel.setCusCode(clCodeMap.get(excel.getCusId()));
                    excel.setCusName(clNameMap.get(excel.getCusId()));
                    excel.setStaCode(cusClCodeMap.get(excel.getStaId()));
                    excel.setStaName(cusClNameMap.get(excel.getStaId()));
                }
                clExcelWriter.write(staClLinkExcelList,clSheet4);
                clExcelWriter.finish();
                staClLinkExcelList.clear();
                simplifyVoList.clear();
                clNameMap.clear();
                cusClCodeMap.clear();
                cusClNameMap.clear();
            }else if(StringUtils.equals(type,ApplyConstants.JX_TYPE)){
                String jxFile = downloadPath +"机械.xlsx";
                ExcelWriter jxExcelWriter = EasyExcel.write(jxFile).build();
                Map<String, String> jxChapterMap;
                List<String> jxIds;
                Map<String, String> jxCodeMap = new HashMap<>();
                Map<String, String> jxNameMap = new HashMap<>();

                WriteSheet jxSheet1 = EasyExcel.writerSheet(0, "章节").head(StaJxChapterExcel.class).build();
                WriteSheet jxSheet2 = EasyExcel.writerSheet(1, "费用项").head(StaJxFeeExcel.class).build();
                WriteSheet jxSheet3 = EasyExcel.writerSheet(2, "关联特征").head(StaClJxLinkFeatureExcel.class).build();
                WriteSheet jxSheet4 = EasyExcel.writerSheet(3, "关联标准机械").head(StaJxLinkExcel.class).build();

                List<StaJxChapterExcel> staJxChapterExcelList = jxChapterMapper.selectExport(versionId);
                jxChapterMap = staJxChapterExcelList.stream().collect(Collectors.toMap(StaJxChapterExcel::getId, StaJxChapterExcel::getChapterName));
                jxExcelWriter.write(staJxChapterExcelList,jxSheet1);
                staJxChapterExcelList.clear();
                List<StaJxFeeExcel> staJxFeeExcelList = jxFeeMapper.selectExport(versionId);
                for (StaJxFeeExcel excel : staJxFeeExcelList) {
                    excel.setChapterName(jxChapterMap.get(excel.getChapterId()));
                    jxCodeMap.put(excel.getId(),excel.getCode());
                    jxNameMap.put(excel.getId(),excel.getItemName());
                }
                jxIds = new ArrayList<>(jxCodeMap.keySet());
                jxExcelWriter.write(staJxFeeExcelList,jxSheet2);
                staJxFeeExcelList.clear();
                jxChapterMap.clear();
                List<StaClJxLinkFeatureExcel> staJxLinkFeatureExcelList = staLinkFeatureMapper.selectClJxExport(versionId,jxIds);
                for (StaClJxLinkFeatureExcel excel : staJxLinkFeatureExcelList) {
                    excel.setCode(jxCodeMap.get(excel.getItemId()));
                    excel.setItemName(jxNameMap.get(excel.getItemId()));
                    excel.setFeatureName(featureDictMap.get(excel.getFeatureId()));
                }
                jxExcelWriter.write(staJxLinkFeatureExcelList,jxSheet3);
                staJxLinkFeatureExcelList.clear();

                List<StaJxLinkExcel> staJxLinkExcelList = staJxLinkMapper.selectExport(versionId,jxIds);
                List<CusMechanicalStaItem> simplifyVoList = cusJxMapper.selectSimplifyList(companyId);
                Map<String, String> cusJxCodeMap = simplifyVoList.stream().collect(Collectors.toMap(CusMechanicalStaItem::getId, CusMechanicalStaItem::getCode));
                Map<String, String> cusJxNameMap = simplifyVoList.stream().collect(Collectors.toMap(CusMechanicalStaItem::getId, CusMechanicalStaItem::getItemName));
                for (StaJxLinkExcel excel : staJxLinkExcelList) {
                    excel.setCusCode(jxCodeMap.get(excel.getCusId()));
                    excel.setCusName(jxNameMap.get(excel.getCusId()));
                    excel.setStaCode(cusJxCodeMap.get(excel.getStaId()));
                    excel.setStaName(cusJxNameMap.get(excel.getStaId()));
                }
                jxExcelWriter.write(staJxLinkExcelList,jxSheet4);
                staJxLinkExcelList.clear();
                simplifyVoList.clear();
                jxCodeMap.clear();
                jxNameMap.clear();
                cusJxCodeMap.clear();
                cusJxNameMap.clear();
                jxExcelWriter.finish();
            }
        }
        return downloadPath;
    }

    private void getGkChildren(ListValueMap<String, GkExcel> listValueMap, GkExcel root,String index) {
        String id = Convert.toStr(root.getId());
        List<GkExcel> childrenList = listValueMap.get(id);
        if (CollUtil.isNotEmpty(childrenList)) {
            Integer indexNew = 0;
            root.setChildren(childrenList);
            for (GkExcel gkExcel : childrenList) {
                indexNew++;
                gkExcel.setIndexOne(index+"."+indexNew);
                getGkChildren(listValueMap,gkExcel,index+"."+indexNew);
            }
        }
    }

    // 定义方法将树形结构数据转换为扁平化数据
    private void flattenTree(List<GkExcel> treeList, List<GkExcel> flatList) {
        for (GkExcel node : treeList) {
            flatList.add(node);
            if (node.getChildren() != null) {
                flattenTree(node.getChildren(), flatList);
            }
        }
    }

    private void setExpenseCategories(List<CusExpenseCategoriesExcel> list,Map<String,String> gkDictMap,Map<String,String> lbDictMap) {
        for (CusExpenseCategoriesExcel excel : list) {
            lbDictMap.put(excel.getId(),excel.getCategoriesName());

            String gkItem = excel.getGkItem();
            Map<String, List<String>> gkItemMap = JSON.parseObject(gkItem, Map.class);

            excel.setHY(setGkItem(gkItemMap.get("HY"),gkDictMap));
            excel.setCB(setGkItem(gkItemMap.get("CB"),gkDictMap));
            excel.setZR(setGkItem(gkItemMap.get("ZR"),gkDictMap));
            excel.setCS(setGkItem(gkItemMap.get("CS"),gkDictMap));
        }
    }
    private String setGkItem(List<String> gkIds,Map<String,String> gkDictMap){
        return gkIds.stream()
                .map(gkDictMap::get)
                .collect(Collectors.joining(","));
    }

    private void setGxLinkGkExcel(List<StaGxLinkGkExcel> list,Map<String,StaGxFeeExcel> gxFeeMap,Map<String,String> featureDictMap,Map<String, String> featureDescribeGkMap,Map<String, String> gkDictMap) {
        for (StaGxLinkGkExcel excel : list) {
            excel.setCode(gxFeeMap.get(excel.getGxId()).getCode());
            excel.setGxName(gxFeeMap.get(excel.getGxId()).getName());
            String featureJson = excel.getFeatureItem();
            if (StringUtils.isNotEmpty(featureJson)) {
                Map<String, List<String>> featureItemMap = JSON.parseObject(featureJson, Map.class);
                StringBuilder featureItem = new StringBuilder();
                List<String> ids = featureItemMap.get("ids");
                if (CollUtil.isNotEmpty(ids)) {
                    List<String> items = featureItemMap.get("items");
                    String lastFeatureId = "";
                    for (int i = 0; i < ids.size(); i++) {
                        String featureId = ids.get(i);
                        if (StringUtils.isEmpty(featureId)) {
                            continue;
                        }
                        String item = items.get(i);
                        if (StringUtils.equals(lastFeatureId, featureId)) {
                            featureItem.append("|").append(item);
                            continue;
                        }
                        String featureName;
                        if (featureDictMap.containsKey(featureId)) {
                            featureName = featureDictMap.get(featureId);
                        } else {
                            featureName = featureDictMap.get(featureId);
                            if (StringUtils.isEmpty(featureName)) {
                                featureName = "id:" + featureId + "被特征字典删除";
                            }
                            featureDictMap.put(featureId, featureName);
                        }
                        featureItem.append(",").append(featureName).append(":").append(item);
                        lastFeatureId = featureId;
                    }
                    excel.setFeatureDescribe(featureItem.substring(1));
                    featureDescribeGkMap.put(excel.getId(), featureItem.substring(1));
                }
            }

            String gkItem = excel.getGkItem();
            Map<String, String> gkItemMap = JSON.parseObject(gkItem, Map.class);
            if (StringUtils.equals(excel.getFeatureState(), "0")) {
                excel.setZR(gkDictMap.get(gkItemMap.get("ZR")));
                excel.setGZ(gkDictMap.get(gkItemMap.get("GZ")));
                excel.setHY(gkDictMap.get(gkItemMap.get("HY")));
                excel.setCB(gkDictMap.get(gkItemMap.get("CB")));
                excel.setCS(gkDictMap.get(gkItemMap.get("CS")));
            } else if (StringUtils.equals(excel.getFeatureState(), "1")) {
                excel.setZR(gkDictMap.get(gkItemMap.get("ZR")));
                excel.setGZ(gkDictMap.get(gkItemMap.get("GZ")));
            } else if (StringUtils.equals(excel.getFeatureState(), "9")) {
                excel.setHY(gkDictMap.get(gkItemMap.get("HY")));
                excel.setCB(gkDictMap.get(gkItemMap.get("CB")));
                excel.setCS(gkDictMap.get(gkItemMap.get("CS")));
            }
        }
    }

    private void setGxFeatureConsumeExcel(List<StaGxFeatureConsumeExcel> list,Map<String,StaGxFeeExcel> gxFeeMap,Map<String,String> featureDictMap,Map<String, String> featureDescribeConsumeMap,Map<String, String> dictAddressMap) {
        for (StaGxFeatureConsumeExcel excel : list) {
            excel.setCode(gxFeeMap.get(excel.getGxId()).getCode());
            excel.setGxName(gxFeeMap.get(excel.getGxId()).getName());
            excel.setAddressName(dictAddressMap.get(excel.getAddress()));

            String featureJson = excel.getFeatureItem();
            if (StringUtils.isNotEmpty(featureJson)) {
                Map<String, List<String>> featureItemMap = JSON.parseObject(featureJson, Map.class);
                StringBuilder featureItem = new StringBuilder();
                List<String> ids = featureItemMap.get("ids");
                if (CollUtil.isNotEmpty(ids)) {
                    List<String> items = featureItemMap.get("items");
                    String lastFeatureId = "";
                    for (int i = 0; i < ids.size(); i++) {
                        String featureId = ids.get(i);
                        if (StringUtils.isEmpty(featureId)) {
                            continue;
                        }
                        String item = items.get(i);
                        if (StringUtils.equals(lastFeatureId, featureId)) {
                            featureItem.append("|").append(item);
                            continue;
                        }
                        String featureName;
                        if (featureDictMap.containsKey(featureId)) {
                            featureName = featureDictMap.get(featureId);
                        } else {
                            featureName = featureDictMap.get(featureId);
                            if (StringUtils.isEmpty(featureName)) {
                                featureName = "id:" + featureId + "被特征字典删除";
                            }
                            featureDictMap.put(featureId, featureName);
                        }
                        featureItem.append(",").append(featureName).append(":").append(item);
                        lastFeatureId = featureId;
                    }
                    excel.setFeatureDescribe(featureItem.substring(1));
                    featureDescribeConsumeMap.put(excel.getId(), featureItem.substring(1));
                }
            }
        }
    }
}
